package thread;

/**
 * 多线程并发安全问题
 * 多个线程并发操作同一临界资源,由于线程切换时机不确定,导致执行顺序出现混乱从而引发
 * 的一系列问题.
 * 临界资源:对该资源的一次完成操作过程同时只能被单一的一个线程进行的.
 */
public class SyncDemo {
    public static void main(String[] args) {
        Table table = new Table();
        Thread t1 = new Thread(){
            public void run(){
                while(true){
                    int bean = table.getBean();
                    Thread.yield();
                    System.out.println(getName()+":"+bean);
                }
            }
        };
        Thread t2 = new Thread(){
            public void run(){
                while(true){
                    int bean = table.getBean();
                    Thread.yield();
                    System.out.println(getName()+":"+bean);
                }
            }
        };
        t1.start();
        t2.start();
    }
}

class Table{
    private int beans = 20;//桌子上有20个豆子

    /**
     * 当一个方法被关键字synchronized修饰后,该方法称为同步方法.
     * 这样的方法多个线程不能同时在方法内部执行.
     * 将多个线程并发操作改为同步(有先后顺序的排队)执行即可解决多线程并发安全问题.
     * @return
     */
    public synchronized int getBean(){//从桌子上取一个豆子
        if(beans==0){
            throw new RuntimeException("没有豆子了!");
        }
        /*
            Thread的今天方法yield()方法的作用:
            让当前线程主动放弃本次剩余时间片,回到RUNNABLE状态,等待下次时间片的分配
         */
        Thread.yield();//yield:让出 模拟执行到这里CPU时间片用尽发生线程切换
        return beans--;
    }
}



